package main

import (
	"fmt"
)

func main() {
	//Go的数组
	//Array数组介绍
	//数组是指一系列同一类型数据的集合。数组中包含的每个数据被称为数组元素（element），这种类型可以是意的原始类型，比如int、string等，也可以是用户自定义的类型。一个数组包含的元素个数被称为数组的长度。在Golang中数组是一个长度固定的数据类型，数组的长度是类型的一部分，也就是说[5]int和[10]int是两个不同的类型。Golang中数组的另一个特点是占用内存的连续性，也就是说数组中的元素是被分配到连续的内存地址中的，因而索引数组元素的速度非常快。
	//
	//和数组对应的类型是Slice（切片），Slice是可以增长和收缩的动态序列，功能也更灵活，但是想要理解slice工作原理的话需要先理解数组，所以本节主要为大家讲解数组的使用。
	//数组定义
	//var 数组变量名 [元素数量] T
	array1 := [5]int{1, 2, 3, 4, 5}
	array2 := [5]string{"a", "b", "c", "d"}
	//fmt.Println(unsafe.Sizeof(array1))
	fmt.Printf("array1: %T\n", array1)
	fmt.Printf("array2: %T\n", array2)
	//	数组的初始化 方法1 创建数组 然后按照下标进行赋值
	//var array3 [5]int
	array3 := [6]int{}
	//var array4 [5]string
	array3[0] = 1
	array3[1] = 10
	array3[2] = 20
	array3[3] = 30
	array3[4] = 40
	fmt.Println(array3)
	//	第二种初始化方法 创建数组的同时直接进行赋值
	var array4 = [10]int{1, 2, 3, 4, 5}
	fmt.Println(array4)
	//	第三种初始化方式 自动判断数组长度
	var array5 = [...]int{1, 2}
	fmt.Println(array5)
	//	第4种初始化的方式 按照下标进行赋值
	var array6 = [...]int{0: 100, 5: 9999}
	fmt.Println(array6)
	//遍历数组
	//	数组遍历 2种方法
	//方法1 正常的for循环 用len确定for的限制条件
	array7 := [...]int{0: 100, 3: 999, 9: 12312}
	for i := 0; i < len(array7); i++ {
		fmt.Println(array7[i])
	}
	//	方法2 使用for range
	var array8 = [...]int{0: 100, 3: 999, 9: 12312}
	for key, val := range array8 {
		fmt.Printf("key: %d, val: %d\n", key, val)
	}

	//数组的值类型
	//数组是值类型，赋值和传参会复制整个数组，因此改变副本的值，不会改变本身的值
	//	数组array是值类型！！！！
	//	例子证明数组为值类型
	array_val1 := [...]int{1, 2, 3, 4, 5}
	array_val2 := array_val1
	array_val2[0] = 10
	fmt.Println(array_val1, array_val2)
	//	[1 2 3 4 5] [10 2 3 4 5] 数组2改变没有影响到数组1
	//	先引入切片数据类型
	//切片定义(引用类型)
	//在golang中，切片的定义和数组定义是相似的，但是需要注意的是，切片是引用数据类型，如下
	//	与上述相同的例子 我们定义两个简单的切片去改变其中的值 观察两个切片的变化
	var slice1 = []int{1, 2, 3, 4, 5}
	slice2 := slice1
	slice2[0] = 100
	fmt.Println(slice1, slice2)
	//	我们可以看到 切片1和切片2 都发生了变化 证明两个切片指向的地址是一致的 切片是引用类型
	//二维数组
	//Go语言支持多维数组，我们这里以二维数组为例（数组中又嵌套数组）
	//var 数组变量名 [元素数量][元素数量] T
	//	我想定义一个2维数组
	var array10 = [2][2]int{{1, 2}, {3, 4}}
	fmt.Println(array10)

	//	二维数组的遍历
	//方式1
	for i := 0; i < len(array10); i++ {
		for j := 0; j < len(array10[i]); j++ {
			fmt.Println(array10[i][j])
		}
	}
	fmt.Println("---------")
	//	方式2
	for _, v1 := range array10 {
		for _, v2 := range v1 {
			fmt.Println(v2)
		}
	}

	//类型推导
	//另外我们在进行数组的创建的时候，还可以使用类型推导，但是只能使用一个 ...
	var array11 = [...][3]int{{1, 11, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}, {1, 1, 1}}
	fmt.Println(array11)
}
